package com.zxmr.webclient.action;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.zxmr.action.Request;
import com.zxmr.action.RequestPayload;
import com.zxmr.action.Session;
import com.zxmr.domain.account.User;
import com.zxmr.domain.component.Component;
import com.zxmr.domain.service.ComponentService;
import com.zxmr.util.ResourceManager;
import com.zxmr.webclient.component.ComponentAsynRequest;
import com.zxmr.webclient.component.ComponentsRepository;
import com.zxmr.webclient.servlet.DispatchExecutors;

@Controller
public class ComponentDispatch {

	@RequestMapping("/dispatch/{component}/**")
	public void dispatch(HttpServletRequest request,HttpServletResponse response,@PathVariable String component)
	{
		AsyncContext aCtx = null;
		aCtx = request.startAsync(request, response); 
		executor.execut(new Worker(aCtx,request,component));
	}
	DispatchExecutors executor = new DispatchExecutors();
	
	class Worker implements Runnable{

		AsyncContext aCtx;
		HttpServletRequest request;
		String componentName;
		
		public Worker(AsyncContext aCtx,HttpServletRequest request,String component)
		{
			this.aCtx = aCtx;
			this.request = request;
			this.componentName = component;
		}
		@Override
		public void run() {
			try
			{
				aCtx.getResponse().setContentType("text/html");
				aCtx.getResponse().setCharacterEncoding("UTF-8");
				User user = (User)request.getSession().getAttribute("user");
				if(user == null)
				{
					aCtx.getResponse().getWriter().println("{\"result\":\""+ResourceManager.getInstance().getMessage("com.user.logon")+"\"}");
					aCtx.complete();
					return;
				}
				Component component = ComponentsRepository.getComponent(componentName);
				if(checkComponentAuthorize(component,user))
				{
					Request re = constructRequest(request,component,user);
					ComponentAsynRequest asynRequest = new ComponentAsynRequest(component,aCtx);
					
					asynRequest.setRequest(re);
					asynRequest.send();
				}else
				{
					aCtx.getResponse().getWriter().println("{\"result\":\"component is not authorized\"}");
					aCtx.complete();
				}

			}catch(Exception e)
			{
				e.printStackTrace();
				try {
					aCtx.getResponse().getWriter().println("{\"result\":\"internal error when dispatch the component request\"}");
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				aCtx.complete();
			}

			
		}
		
	}
	public boolean checkComponentAuthorize(Component component,User user)
	{
		if(component == null)return false;
		ComponentService service = new ComponentService();
		return service.isCompanyAuthorized(user.getCompany(), component.getId());
	}

	private String getRequestComponentPath(HttpServletRequest request,String componentName)
	{
		String componentPath = "/dispatch/"+componentName;
		String uri = request.getRequestURI();
		int position = uri.indexOf(componentPath);
		String result = uri.substring(position+componentPath.length());
		return result;
	}
	private Map<String,String> convertParameters(HttpServletRequest request)
	{
		Map<String,String> map = new HashMap<String,String>();
		Enumeration<String> em = request.getParameterNames();
		while(em.hasMoreElements())
		{
			String name = em.nextElement();
			String value = request.getParameter(name);
			map.put(name, value);
		}
		return map;
	}
	private Request constructRequest(HttpServletRequest request,Component component,User user)
	{
		
		String componentPath = getRequestComponentPath(request,component.getName());
		
		Request re = new Request();
		Session se = new Session();
		se.setSessionID(request.getSession().getId());
		
		re.setAccount(user);
		re.setNeedResponse(true);
		re.setSession(se);
		
		RequestPayload payload  = new RequestPayload();
		payload.setUrl(componentPath);
		payload.setParameters(convertParameters(request));
		re.setPayload(payload);
		
		return re;
	}
}
